namespace DotNetNuke.Services.Scheduling.DNNScheduling
{
    using DotNetNuke.Common;
    using DotNetNuke.Common.Utilities;
    using DotNetNuke.Services.Exceptions;
    using DotNetNuke.Services.Log.EventLog;
    using DotNetNuke.Services.Scheduling;
    using Microsoft.VisualBasic;
    using Microsoft.VisualBasic.CompilerServices;
    using System;
    using System.Collections;
    using System.Text;
    using System.Threading;

    [StandardModule]
    internal sealed class Scheduler
    {
        public class CoreScheduler
        {
            private static Collection _ScheduleInProgress;
            private static Collection _ScheduleQueue;
            private static int ActiveThreadCount;
            private static ProcessGroup[] arrProcessGroup;
            private static bool Debug = false;
            private static bool ForceReloadSchedule = false;
            public static bool KeepRunning = true;
            public static bool KeepThreadAlive = true;
            private static int MaxThreadCount;
            private static int NumberOfProcessGroups;
            private static ReaderWriterLock objInProgressReadWriteLock = new ReaderWriterLock();
            private static ReaderWriterLock objQueueReadWriteLock = new ReaderWriterLock();
            private static ReaderWriterLock objStatusReadWriteLock = new ReaderWriterLock();
            private static int ReaderTimeouts = 0;
            private static int Reads = 0;
            private static int ReadTimeout = 0xafc8;
            private static ScheduleStatus Status = ScheduleStatus.STOPPED;
            private static bool ThreadPoolInitialized = false;
            private static int WriterTimeouts = 0;
            private static int Writes = 0;
            private static int WriteTimeout = 0xafc8;

            public CoreScheduler(int MaxThreads)
            {
                if (!ThreadPoolInitialized)
                {
                    this.InitializeThreadPool(MaxThreads);
                }
            }

            public CoreScheduler(bool boolDebug, int MaxThreads)
            {
                Debug = boolDebug;
                if (!ThreadPoolInitialized)
                {
                    this.InitializeThreadPool(MaxThreads);
                }
            }

            public static ScheduleHistoryItem AddScheduleHistory(ScheduleHistoryItem objScheduleHistoryItem)
            {
                try
                {
                    int intScheduleHistoryID = new SchedulingController().AddScheduleHistory(objScheduleHistoryItem);
                    objScheduleHistoryItem.ScheduleHistoryID = intScheduleHistoryID;
                }
                catch (Exception exception1)
                {
    
                    Exception exc = exception1;
                    DotNetNuke.Services.Exceptions.Exceptions.ProcessSchedulerException(exc);
    
                }
                return objScheduleHistoryItem;
            }

            private static void AddToScheduleInProgress(ScheduleHistoryItem objScheduleHistoryItem)
            {
                try
                {
                    objInProgressReadWriteLock.AcquireWriterLock(WriteTimeout);
                    try
                    {
                        ScheduleInProgress.Add(objScheduleHistoryItem, objScheduleHistoryItem.ScheduleID.ToString(), null, null);
                        Interlocked.Increment(ref Writes);
                    }
                    finally
                    {
                        objInProgressReadWriteLock.ReleaseWriterLock();
                    }
                }
                catch (ApplicationException exception1)
                {
    
                    ApplicationException ex = exception1;
                    Interlocked.Increment(ref WriterTimeouts);
                    DotNetNuke.Services.Exceptions.Exceptions.LogException(ex);
    
                }
            }

            public static void AddToScheduleQueue(ScheduleHistoryItem objScheduleHistoryItem)
            {
                if (!ScheduleQueueContains(objScheduleHistoryItem))
                {
                    try
                    {
                        objQueueReadWriteLock.AcquireWriterLock(WriteTimeout);
                        try
                        {
                            ScheduleQueue.Add(objScheduleHistoryItem, objScheduleHistoryItem.ScheduleID.ToString(), null, null);
                            Interlocked.Increment(ref Writes);
                        }
                        finally
                        {
                            objQueueReadWriteLock.ReleaseWriterLock();
                        }
                    }
                    catch (ApplicationException exception1)
                    {
        
                        ApplicationException ex = exception1;
                        Interlocked.Increment(ref WriterTimeouts);
                        DotNetNuke.Services.Exceptions.Exceptions.LogException(ex);
        
                    }
                }
            }

            private static void ClearScheduleQueue()
            {
                try
                {
                    int intCount = GetScheduleQueueCount();
                    if (intCount != 0)
                    {
                        objQueueReadWriteLock.AcquireWriterLock(WriteTimeout);
                        try
                        {
                            int refIntHelperL0 = intCount;
                            for (int i = 1; i <= refIntHelperL0; i++)
                            {
                                ScheduleQueue.Remove(i);
                            }
                            Interlocked.Increment(ref Writes);
                        }
                        finally
                        {
                            objQueueReadWriteLock.ReleaseWriterLock();
                        }
                    }
                }
                catch (ApplicationException exception1)
                {
    
                    ApplicationException ex = exception1;
                    Interlocked.Increment(ref WriterTimeouts);
                    DotNetNuke.Services.Exceptions.Exceptions.LogException(ex);
    
                }
            }

            ~CoreScheduler()
            {
            }

            public static void FireEvents(bool Asynchronous)
            {
                int intScheduleQueueCount = GetScheduleQueueCount();
                int numToRun = intScheduleQueueCount;
                int numRun = 0;
                int refIntHelperL0 = intScheduleQueueCount - 1;
                for (int i = 0; i <= refIntHelperL0; i++)
                {
                    if (!KeepRunning)
                    {
                        break;
                    }
                    int ProcessGroup = GetProcessGroup();
                    ScheduleItem objScheduleItem = (ScheduleItem) ScheduleQueue[i + 1];
                    if (((((DateTime.Compare(objScheduleItem.NextStart, DateAndTime.Now) <= 0) && objScheduleItem.Enabled) && ((!IsInProgress(objScheduleItem) && !HasDependenciesConflict(objScheduleItem)) && (numRun < numToRun))) ? 1 : 0) != 0)
                    {
                        objScheduleItem.ProcessGroup = ProcessGroup;
                        if (SchedulingProvider.SchedulerMode == SchedulerMode.TIMER_METHOD)
                        {
                            objScheduleItem.ScheduleSource = ScheduleSource.STARTED_FROM_TIMER;
                        }
                        else if (SchedulingProvider.SchedulerMode == SchedulerMode.REQUEST_METHOD)
                        {
                            objScheduleItem.ScheduleSource = ScheduleSource.STARTED_FROM_BEGIN_REQUEST;
                        }
                        if (Asynchronous)
                        {
                            arrProcessGroup[ProcessGroup].AddQueueUserWorkItem(objScheduleItem);
                        }
                        else
                        {
                            arrProcessGroup[ProcessGroup].RunSingleTask(objScheduleItem);
                        }
                        if (Debug)
                        {
                            EventLogController objEventLog = new EventLogController();
                            LogInfo objEventLogInfo = new LogInfo();
                            objEventLogInfo.AddProperty("EVENT ADDED TO PROCESS GROUP " + objScheduleItem.ProcessGroup.ToString(), objScheduleItem.TypeFullName);
                            objEventLogInfo.AddProperty("SCHEDULE ID", objScheduleItem.ScheduleID.ToString());
                            objEventLogInfo.LogTypeKey = "DEBUG";
                            objEventLog.AddLog(objEventLogInfo);
                        }
                        numRun++;
                    }
                    else if (Debug)
                    {
                        bool appended = false;
                        StringBuilder strDebug = new StringBuilder("Task not run because ");
                        if (DateTime.Compare(objScheduleItem.NextStart, DateAndTime.Now) > 0)
                        {
                            strDebug.Append(" task is scheduled for " + objScheduleItem.NextStart.ToString());
                            appended = true;
                        }
                        if (!objScheduleItem.Enabled)
                        {
                            if (appended)
                            {
                                strDebug.Append(" and");
                            }
                            strDebug.Append(" task is not enabled");
                            appended = true;
                        }
                        if (IsInProgress(objScheduleItem))
                        {
                            if (appended)
                            {
                                strDebug.Append(" and");
                            }
                            strDebug.Append(" task is already in progress");
                            appended = true;
                        }
                        if (HasDependenciesConflict(objScheduleItem))
                        {
                            if (appended)
                            {
                                strDebug.Append(" and");
                            }
                            strDebug.Append(" task has conflicting dependency");
                            appended = true;
                        }
                        EventLogController objEventLog = new EventLogController();
                        LogInfo objEventLogInfo = new LogInfo();
                        objEventLogInfo.AddProperty("EVENT NOT RUN REASON", strDebug.ToString());
                        objEventLogInfo.AddProperty("SCHEDULE ID", objScheduleItem.ScheduleID.ToString());
                        objEventLogInfo.AddProperty("TYPE FULL NAME", objScheduleItem.TypeFullName);
                        objEventLogInfo.LogTypeKey = "DEBUG";
                        objEventLog.AddLog(objEventLogInfo);
                    }
                }
            }

            public static int GetActiveThreadCount()
            {
                return ActiveThreadCount;
            }

            public static int GetFreeThreadCount()
            {
                return FreeThreads;
            }

            public static int GetMaxThreadCount()
            {
                return MaxThreadCount;
            }

            private static int GetProcessGroup()
            {
                Random r = new Random();
                return r.Next(0, NumberOfProcessGroups - 1);
            }

            public static Collection GetScheduleInProgress()
            {
                Collection c = null;
                try
                {
                    objInProgressReadWriteLock.AcquireReaderLock(ReadTimeout);
                    try
                    {
                        c = ScheduleInProgress;
                        Interlocked.Increment(ref Reads);
                    }
                    finally
                    {
                        objInProgressReadWriteLock.ReleaseReaderLock();
                    }
                }
                catch (ApplicationException exception1)
                {
    
                    ApplicationException ex = exception1;
                    Interlocked.Increment(ref ReaderTimeouts);
    
                }
                return c;
            }

            public static int GetScheduleInProgressCount()
            {
                int intCount=0;
                try
                {
                    objInProgressReadWriteLock.AcquireReaderLock(ReadTimeout);
                    try
                    {
                        intCount = ScheduleInProgress.Count;
                        Interlocked.Increment(ref Reads);
                    }
                    finally
                    {
                        objInProgressReadWriteLock.ReleaseReaderLock();
                    }
                }
                catch (ApplicationException exception1)
                {
    
                    ApplicationException ex = exception1;
                    Interlocked.Increment(ref ReaderTimeouts);
    
                }
                return intCount;
            }

            public static Collection GetScheduleQueue()
            {
                Collection c = null;
                try
                {
                    objQueueReadWriteLock.AcquireReaderLock(ReadTimeout);
                    try
                    {
                        c = ScheduleQueue;
                        Interlocked.Increment(ref Reads);
                    }
                    finally
                    {
                        objQueueReadWriteLock.ReleaseReaderLock();
                    }
                }
                catch (ApplicationException exception1)
                {
    
                    ApplicationException ex = exception1;
                    Interlocked.Increment(ref ReaderTimeouts);
    
                }
                return c;
            }

            public static int GetScheduleQueueCount()
            {
                int intCount=0;
                try
                {
                    objQueueReadWriteLock.AcquireReaderLock(ReadTimeout);
                    try
                    {
                        intCount = ScheduleQueue.Count;
                        Interlocked.Increment(ref Reads);
                    }
                    finally
                    {
                        objQueueReadWriteLock.ReleaseReaderLock();
                    }
                }
                catch (ApplicationException exception1)
                {
    
                    ApplicationException ex = exception1;
                    Interlocked.Increment(ref ReaderTimeouts);
    
                }
                return intCount;
            }

            public static ScheduleStatus GetScheduleStatus()
            {
                ScheduleStatus s=ScheduleStatus.NOT_SET;
                try
                {
                    objStatusReadWriteLock.AcquireReaderLock(ReadTimeout);
                    try
                    {
                        s = Status;
                    }
                    finally
                    {
                        objStatusReadWriteLock.ReleaseReaderLock();
                    }
                }
                catch (ApplicationException exception1)
                {
    
                    ApplicationException ex = exception1;
                    Interlocked.Increment(ref ReaderTimeouts);
    
                }
                return s;
            }

            public static void Halt(string SourceOfHalt)
            {
                if (SchedulingProvider.SchedulerMode != SchedulerMode.REQUEST_METHOD)
                {
                    int endLoopIntHelperS0;
                    EventLogController objEventLog = new EventLogController();
                    LogInfo objEventLogInfo = new LogInfo();
                    SetScheduleStatus(ScheduleStatus.SHUTTING_DOWN);
                    objEventLogInfo = new LogInfo();
                    objEventLogInfo.AddProperty("Initiator", SourceOfHalt);
                    objEventLogInfo.LogTypeKey = "SCHEDULER_SHUTTING_DOWN";
                    objEventLog.AddLog(objEventLogInfo);
                    KeepRunning = false;
                    int i = 0;
                    do
                    {
                        if (GetScheduleStatus() == ScheduleStatus.STOPPED)
                        {
                            return;
                        }
                        Thread.Sleep(0x3e8);
                        i++;
                        endLoopIntHelperS0 = 120;
                    }
                    while (i <= endLoopIntHelperS0);
                }
                ActiveThreadCount = 0;
            }

            public static bool HasDependenciesConflict(ScheduleItem objScheduleItem)
            {
                bool objReturn = false;
                try
                {
                    objInProgressReadWriteLock.AcquireReaderLock(ReadTimeout);
                    try
                    {
                        if ((ScheduleInProgress != null) & (objScheduleItem.ObjectDependencies.Length > 0))
                        {
                            int refIntHelperL0 = ScheduleInProgress.Count;
                            for (int i = 1; i <= refIntHelperL0; i++)
                            {
                                ScheduleItem obj = (ScheduleItem) ScheduleInProgress[i];
                                if ((obj.ObjectDependencies.Length > 0) && obj.HasObjectDependencies(objScheduleItem.ObjectDependencies))
                                {
                                    objReturn = true;
                                }
                            }
                        }
                        Interlocked.Increment(ref Reads);
                    }
                    finally
                    {
                        objInProgressReadWriteLock.ReleaseReaderLock();
                    }
                }
                catch (ApplicationException exception1)
                {
    
                    ApplicationException ex = exception1;
                    Interlocked.Increment(ref ReaderTimeouts);
    
                }
                return objReturn;
            }

            private void InitializeThreadPool(int MaxThreads)
            {
                if (MaxThreads == -1)
                {
                    MaxThreads = 1;
                }
                NumberOfProcessGroups = MaxThreads;
                MaxThreadCount = MaxThreads;
                int refIntHelperL0 = NumberOfProcessGroups - 1;
                for (int i = 0; i <= refIntHelperL0; i++)
                {
                    arrProcessGroup = (ProcessGroup[]) Utils.CopyArray((Array) arrProcessGroup, new ProcessGroup[i + 1]);
                    arrProcessGroup[i] = new ProcessGroup();
                }
                ThreadPoolInitialized = true;
            }

            private static bool IsInProgress(ScheduleItem objScheduleItem)
            {
                bool objReturn = false;
                try
                {
                    objInProgressReadWriteLock.AcquireReaderLock(ReadTimeout);
                    try
                    {
                        if (ScheduleInProgress.Count > 0)
                        {
                            int refIntHelperL0 = ScheduleInProgress.Count;
                            for (int i = 1; i <= refIntHelperL0; i++)
                            {
                                ScheduleItem obj = (ScheduleItem) ScheduleInProgress[i];
                                if (obj.ScheduleID == objScheduleItem.ScheduleID)
                                {
                                    objReturn = true;
                                }
                            }
                        }
                        Interlocked.Increment(ref Reads);
                    }
                    finally
                    {
                        objInProgressReadWriteLock.ReleaseReaderLock();
                    }
                }
                catch (ApplicationException exception1)
                {
    
                    ApplicationException ex = exception1;
                    Interlocked.Increment(ref ReaderTimeouts);
    
                }
                return objReturn;
            }

            internal static bool IsInQueue(ScheduleItem objScheduleItem)
            {
                bool objReturn = false;
                try
                {
                    objQueueReadWriteLock.AcquireReaderLock(ReadTimeout);
                    try
                    {
                        if (GetScheduleQueueCount() > 0)
                        {
                            int refIntHelperL0 = GetScheduleQueueCount();
                            for (int i = 1; i <= refIntHelperL0; i++)
                            {
                                ScheduleItem obj = (ScheduleItem) ScheduleQueue[i];
                                if (obj.ScheduleID == objScheduleItem.ScheduleID)
                                {
                                    objReturn = true;
                                }
                            }
                        }
                        Interlocked.Increment(ref Reads);
                    }
                    finally
                    {
                        objQueueReadWriteLock.ReleaseReaderLock();
                    }
                }
                catch (ApplicationException exception1)
                {
    
                    ApplicationException ex = exception1;
                    Interlocked.Increment(ref ReaderTimeouts);
    
                }
                return objReturn;
            }

            public static void LoadQueueFromEvent(EventName EventName)
            {
                ArrayList a = new SchedulingController().GetScheduleByEvent(EventName.ToString(), DotNetNuke.Common.Globals.ServerName);
                int refIntHelperL0 = a.Count - 1;
                for (int i = 0; i <= refIntHelperL0; i++)
                {
                    ScheduleHistoryItem objScheduleHistoryItem = (ScheduleHistoryItem) a[i];
                    if ((((!IsInQueue(objScheduleHistoryItem) && !IsInProgress(objScheduleHistoryItem)) && (!HasDependenciesConflict(objScheduleHistoryItem) && objScheduleHistoryItem.Enabled)) ? 1 : 0) != 0)
                    {
                        objScheduleHistoryItem.ScheduleSource = ScheduleSource.STARTED_FROM_EVENT;
                        AddToScheduleQueue(objScheduleHistoryItem);
                    }
                }
            }

            public static void LoadQueueFromTimer()
            {
                ForceReloadSchedule = false;
                ArrayList a = new SchedulingController().GetSchedule();
                int refIntHelperL0 = a.Count - 1;
                for (int i = 0; i <= refIntHelperL0; i++)
                {
                    ScheduleHistoryItem objScheduleHistoryItem = (ScheduleHistoryItem) a[i];
                    if ((((!IsInQueue(objScheduleHistoryItem) && (objScheduleHistoryItem.TimeLapse != Null.NullInteger)) && ((objScheduleHistoryItem.TimeLapseMeasurement != Null.NullString) && objScheduleHistoryItem.Enabled)) ? 1 : 0) != 0)
                    {
                        if (SchedulingProvider.SchedulerMode == SchedulerMode.TIMER_METHOD)
                        {
                            objScheduleHistoryItem.ScheduleSource = ScheduleSource.STARTED_FROM_TIMER;
                        }
                        else if (SchedulingProvider.SchedulerMode == SchedulerMode.REQUEST_METHOD)
                        {
                            objScheduleHistoryItem.ScheduleSource = ScheduleSource.STARTED_FROM_BEGIN_REQUEST;
                        }
                        AddToScheduleQueue(objScheduleHistoryItem);
                    }
                }
            }

            public static void PurgeScheduleHistory()
            {
                new SchedulingController().PurgeScheduleHistory();
            }

            public static void ReloadSchedule()
            {
                ForceReloadSchedule = true;
            }

            private static void RemoveFromScheduleInProgress(ScheduleItem objScheduleItem)
            {
                try
                {
                    objInProgressReadWriteLock.AcquireWriterLock(WriteTimeout);
                    try
                    {
                        ScheduleInProgress.Remove(objScheduleItem.ScheduleID.ToString());
                        Interlocked.Increment(ref Writes);
                    }
                    catch (ArgumentException exception1)
                    {
        
                        ArgumentException exc = exception1;
        
                    }
                    finally
                    {
                        objInProgressReadWriteLock.ReleaseWriterLock();
                    }
                }
                catch (ApplicationException exception2)
                {
                    ProjectData.SetProjectError(exception2);
                    ApplicationException ex = exception2;
                    Interlocked.Increment(ref WriterTimeouts);
                    DotNetNuke.Services.Exceptions.Exceptions.LogException(ex);
    
                }
            }

            public static void RemoveFromScheduleQueue(ScheduleItem objScheduleItem)
            {
                try
                {
                    objQueueReadWriteLock.AcquireWriterLock(WriteTimeout);
                    try
                    {
                        ScheduleQueue.Remove(objScheduleItem.ScheduleID.ToString());
                        Interlocked.Increment(ref Writes);
                    }
                    catch (ArgumentException exception1)
                    {
        
                        ArgumentException exc = exception1;
        
                    }
                    finally
                    {
                        objQueueReadWriteLock.ReleaseWriterLock();
                    }
                }
                catch (ApplicationException exception2)
                {
                    ProjectData.SetProjectError(exception2);
                    ApplicationException ex = exception2;
                    Interlocked.Increment(ref WriterTimeouts);
                    DotNetNuke.Services.Exceptions.Exceptions.LogException(ex);
    
                }
            }

            public static void RunEventSchedule(EventName EventName)
            {
                try
                {
                    EventLogController objEventLog = new EventLogController();
                    LogInfo objEventLogInfo = new LogInfo();
                    objEventLogInfo.AddProperty("EVENT", EventName.ToString());
                    objEventLogInfo.LogTypeKey = "SCHEDULE_FIRED_FROM_EVENT";
                    objEventLog.AddLog(objEventLogInfo);
                    LoadQueueFromEvent(EventName);
                    while (GetScheduleQueueCount() > 0)
                    {
                        SetScheduleStatus(ScheduleStatus.RUNNING_EVENT_SCHEDULE);
                        try
                        {
                            objQueueReadWriteLock.AcquireReaderLock(ReadTimeout);
                            try
                            {
                                if (GetScheduleQueueCount() > 0)
                                {
                                    FireEvents(true);
                                }
                                Interlocked.Increment(ref Reads);
                            }
                            finally
                            {
                                objQueueReadWriteLock.ReleaseReaderLock();
                            }
                        }
                        catch (ApplicationException exception1)
                        {
            
                            ApplicationException ex = exception1;
                            Interlocked.Increment(ref ReaderTimeouts);
            
                        }
                        if ((WriterTimeouts > 20) | (ReaderTimeouts > 20))
                        {
                            Thread.Sleep(0x927c0);
                        }
                        else
                        {
                            Thread.Sleep(0x2710);
                        }
                        if (GetScheduleQueueCount() == 0)
                        {
                            return;
                        }
                    }
                }
                catch (Exception exception2)
                {
                    ProjectData.SetProjectError(exception2);
                    Exception exc = exception2;
                    DotNetNuke.Services.Exceptions.Exceptions.ProcessSchedulerException(exc);
    
                }
            }

            private static bool ScheduleQueueContains(ScheduleItem objScheduleItem)
            {
                int refIntHelperL0 = GetScheduleQueueCount();
                for (int i = 1; i <= refIntHelperL0; i++)
                {
                    ScheduleItem objScheduleItem2 = (ScheduleItem) ScheduleQueue[i];
                    if (objScheduleItem2.ScheduleID == objScheduleItem.ScheduleID)
                    {
                        return true;
                    }
                }
                return false;
            }

            public static void SetScheduleStatus(ScheduleStatus objScheduleStatus)
            {
                try
                {
                    objStatusReadWriteLock.AcquireWriterLock(WriteTimeout);
                    try
                    {
                        Status = objScheduleStatus;
                        Interlocked.Increment(ref Writes);
                    }
                    finally
                    {
                        objStatusReadWriteLock.ReleaseWriterLock();
                    }
                }
                catch (ApplicationException exception1)
                {
    
                    ApplicationException ex = exception1;
                    Interlocked.Increment(ref WriterTimeouts);
                    DotNetNuke.Services.Exceptions.Exceptions.LogException(ex);
    
                }
            }

            public static void Start()
            {
                try
                {
                    ActiveThreadCount = 0;
                    if ((SchedulingProvider.SchedulerMode != SchedulerMode.REQUEST_METHOD) | Debug)
                    {
                        EventLogController objEventLog = new EventLogController();
                        LogInfo objEventLogInfo = new LogInfo();
                        objEventLogInfo.LogTypeKey = "SCHEDULER_STARTED";
                        objEventLog.AddLog(objEventLogInfo);
                    }
                    while (KeepRunning)
                    {
                        try
                        {
                            if (SchedulingProvider.SchedulerMode == SchedulerMode.TIMER_METHOD)
                            {
                                SetScheduleStatus(ScheduleStatus.RUNNING_TIMER_SCHEDULE);
                            }
                            else
                            {
                                SetScheduleStatus(ScheduleStatus.RUNNING_REQUEST_SCHEDULE);
                            }
                            LoadQueueFromTimer();
                            DateTime LastQueueRefresh = DateAndTime.Now;
                            bool RefreshQueueSchedule = false;
                            while ((((FreeThreads > 0) & !RefreshQueueSchedule) & KeepRunning) & !ForceReloadSchedule)
                            {
                                try
                                {
                                    if (SchedulingProvider.SchedulerMode == SchedulerMode.TIMER_METHOD)
                                    {
                                        SetScheduleStatus(ScheduleStatus.RUNNING_TIMER_SCHEDULE);
                                    }
                                    else
                                    {
                                        SetScheduleStatus(ScheduleStatus.RUNNING_REQUEST_SCHEDULE);
                                    }
                                    objQueueReadWriteLock.AcquireReaderLock(ReadTimeout);
                                    try
                                    {
                                        if (GetScheduleQueueCount() > 0)
                                        {
                                            FireEvents(true);
                                        }
                                        if (!KeepThreadAlive)
                                        {
                                            return;
                                        }
                                        Interlocked.Increment(ref Reads);
                                    }
                                    finally
                                    {
                                        objQueueReadWriteLock.ReleaseReaderLock();
                                    }
                                }
                                catch (ApplicationException exception1)
                                {
                    
                                    ApplicationException ex = exception1;
                                    Interlocked.Increment(ref ReaderTimeouts);
                    
                                }
                                if ((WriterTimeouts > 20) | (ReaderTimeouts > 20))
                                {
                                    if (!KeepRunning)
                                    {
                                        return;
                                    }
                                    Thread.Sleep(0x927c0);
                                }
                                else
                                {
                                    if (KeepRunning)
                                    {
                                        Thread.Sleep(0x2710);
                                    }
                                    else
                                    {
                                        return;
                                    }
                                    if (((DateTime.Compare(LastQueueRefresh.AddMinutes(10.0), DateAndTime.Now) <= 0) | ForceReloadSchedule) & (FreeThreads == MaxThreadCount))
                                    {
                                        RefreshQueueSchedule = true;
                                        break;
                                    }
                                }
                            }
                            if (!KeepRunning)
                            {
                                return;
                            }
                            if (!RefreshQueueSchedule)
                            {
                                SetScheduleStatus(ScheduleStatus.WAITING_FOR_OPEN_THREAD);
                                Thread.Sleep(0x2710);
                            }
                            continue;
                        }
                        catch (Exception exception2)
                        {
                            ProjectData.SetProjectError(exception2);
                            Exception exc = exception2;
                            DotNetNuke.Services.Exceptions.Exceptions.ProcessSchedulerException(exc);
                            Thread.Sleep(0x927c0);
            
                        }
                    }
                }
                finally
                {
                    if ((SchedulingProvider.SchedulerMode == SchedulerMode.TIMER_METHOD) | (SchedulingProvider.SchedulerMode == SchedulerMode.DISABLED))
                    {
                        SetScheduleStatus(ScheduleStatus.STOPPED);
                    }
                    else
                    {
                        SetScheduleStatus(ScheduleStatus.WAITING_FOR_REQUEST);
                    }
                    if ((SchedulingProvider.SchedulerMode != SchedulerMode.REQUEST_METHOD) | Debug)
                    {
                        EventLogController objEventLog = new EventLogController();
                        LogInfo objEventLogInfo = new LogInfo();
                        objEventLogInfo.LogTypeKey = "SCHEDULER_STOPPED";
                        objEventLog.AddLog(objEventLogInfo);
                    }
                }
            }

            public static void UpdateScheduleHistory(ScheduleHistoryItem objScheduleHistoryItem)
            {
                try
                {
                    new SchedulingController().UpdateScheduleHistory(objScheduleHistoryItem);
                }
                catch (Exception exception1)
                {
    
                    Exception exc = exception1;
                    DotNetNuke.Services.Exceptions.Exceptions.ProcessSchedulerException(exc);
    
                }
            }

            public static void WorkCompleted(ref SchedulerClient objSchedulerClient)
            {
                try
                {
                    ScheduleHistoryItem objScheduleHistoryItem = objSchedulerClient.ScheduleHistoryItem;
                    RemoveFromScheduleInProgress(objScheduleHistoryItem);
                    Interlocked.Decrement(ref ActiveThreadCount);
                    objScheduleHistoryItem.EndDate = DateAndTime.Now;
                    if (objScheduleHistoryItem.ScheduleSource == ScheduleSource.STARTED_FROM_EVENT)
                    {
                        objScheduleHistoryItem.NextStart = Null.NullDate;
                    }
                    else if (objScheduleHistoryItem.CatchUpEnabled)
                    {
                        switch (objScheduleHistoryItem.TimeLapseMeasurement)
                        {
                            case "s":
                                objScheduleHistoryItem.NextStart = objScheduleHistoryItem.NextStart.AddSeconds((double) objScheduleHistoryItem.TimeLapse);
                                break;

                            case "m":
                                objScheduleHistoryItem.NextStart = objScheduleHistoryItem.NextStart.AddMinutes((double) objScheduleHistoryItem.TimeLapse);
                                break;

                            case "h":
                                objScheduleHistoryItem.NextStart = objScheduleHistoryItem.NextStart.AddHours((double) objScheduleHistoryItem.TimeLapse);
                                break;

                            case "d":
                                objScheduleHistoryItem.NextStart = objScheduleHistoryItem.NextStart.AddDays((double) objScheduleHistoryItem.TimeLapse);
                                break;
                        }
                    }
                    else
                    {
                        switch (objScheduleHistoryItem.TimeLapseMeasurement)
                        {
                            case "s":
                                objScheduleHistoryItem.NextStart = objScheduleHistoryItem.StartDate.AddSeconds((double) objScheduleHistoryItem.TimeLapse);
                                break;

                            case "m":
                                objScheduleHistoryItem.NextStart = objScheduleHistoryItem.StartDate.AddMinutes((double) objScheduleHistoryItem.TimeLapse);
                                break;

                            case "h":
                                objScheduleHistoryItem.NextStart = objScheduleHistoryItem.StartDate.AddHours((double) objScheduleHistoryItem.TimeLapse);
                                break;

                            case "d":
                                objScheduleHistoryItem.NextStart = objScheduleHistoryItem.StartDate.AddDays((double) objScheduleHistoryItem.TimeLapse);
                                break;
                        }
                    }
                    UpdateScheduleHistory(objScheduleHistoryItem);
                    LogInfo objEventLogInfo = new LogInfo();
                    if (DateTime.Compare(objScheduleHistoryItem.NextStart, Null.NullDate) != 0)
                    {
                        objScheduleHistoryItem.StartDate = Null.NullDate;
                        objScheduleHistoryItem.EndDate = Null.NullDate;
                        objScheduleHistoryItem.LogNotes = "";
                        objScheduleHistoryItem.ProcessGroup = -1;
                        AddToScheduleQueue(objScheduleHistoryItem);
                    }
                    if (objSchedulerClient.ScheduleHistoryItem.RetainHistoryNum > 0)
                    {
                        EventLogController objEventLog = new EventLogController();
                        objEventLogInfo.AddProperty("TYPE", objSchedulerClient.GetType().FullName);
                        objEventLogInfo.AddProperty("THREAD ID", Thread.CurrentThread.GetHashCode().ToString());
                        objEventLogInfo.AddProperty("NEXT START", Convert.ToString(objScheduleHistoryItem.NextStart));
                        objEventLogInfo.AddProperty("SOURCE", objSchedulerClient.ScheduleHistoryItem.ScheduleSource.ToString());
                        objEventLogInfo.AddProperty("ACTIVE THREADS", ActiveThreadCount.ToString());
                        objEventLogInfo.AddProperty("FREE THREADS", FreeThreads.ToString());
                        objEventLogInfo.AddProperty("READER TIMEOUTS", ReaderTimeouts.ToString());
                        objEventLogInfo.AddProperty("WRITER TIMEOUTS", WriterTimeouts.ToString());
                        objEventLogInfo.AddProperty("IN PROGRESS", GetScheduleInProgressCount().ToString());
                        objEventLogInfo.AddProperty("IN QUEUE", GetScheduleQueueCount().ToString());
                        objEventLogInfo.LogTypeKey = "SCHEDULER_EVENT_COMPLETED";
                        objEventLog.AddLog(objEventLogInfo);
                    }
                }
                catch (Exception exception1)
                {
    
                    Exception exc = exception1;
                    DotNetNuke.Services.Exceptions.Exceptions.ProcessSchedulerException(exc);
    
                }
            }

            public static void WorkErrored(ref SchedulerClient objSchedulerClient, ref Exception objException)
            {
                try
                {
                    ScheduleHistoryItem objScheduleHistoryItem = objSchedulerClient.ScheduleHistoryItem;
                    RemoveFromScheduleInProgress(objScheduleHistoryItem);
                    Interlocked.Decrement(ref ActiveThreadCount);
                    DotNetNuke.Services.Exceptions.Exceptions.ProcessSchedulerException(objException);
                    objScheduleHistoryItem.EndDate = DateAndTime.Now;
                    if (objScheduleHistoryItem.ScheduleSource == ScheduleSource.STARTED_FROM_EVENT)
                    {
                        objScheduleHistoryItem.NextStart = Null.NullDate;
                    }
                    else if (objScheduleHistoryItem.RetryTimeLapse != Null.NullInteger)
                    {
                        switch (objScheduleHistoryItem.RetryTimeLapseMeasurement)
                        {
                            case "s":
                                objScheduleHistoryItem.NextStart = objScheduleHistoryItem.StartDate.AddSeconds((double) objScheduleHistoryItem.RetryTimeLapse);
                                goto Label_0150;

                            case "m":
                                objScheduleHistoryItem.NextStart = objScheduleHistoryItem.StartDate.AddMinutes((double) objScheduleHistoryItem.RetryTimeLapse);
                                goto Label_0150;

                            case "h":
                                objScheduleHistoryItem.NextStart = objScheduleHistoryItem.StartDate.AddHours((double) objScheduleHistoryItem.RetryTimeLapse);
                                break;

                            case "d":
                                objScheduleHistoryItem.NextStart = objScheduleHistoryItem.StartDate.AddDays((double) objScheduleHistoryItem.RetryTimeLapse);
                                break;
                        }
                    }
                Label_0150:
                    UpdateScheduleHistory(objScheduleHistoryItem);
                    if ((((DateTime.Compare(objScheduleHistoryItem.NextStart, Null.NullDate) != 0) && (objScheduleHistoryItem.RetryTimeLapse != Null.NullInteger)) ? 1 : 0) != 0)
                    {
                        objScheduleHistoryItem.StartDate = Null.NullDate;
                        objScheduleHistoryItem.EndDate = Null.NullDate;
                        objScheduleHistoryItem.LogNotes = "";
                        objScheduleHistoryItem.ProcessGroup = -1;
                        AddToScheduleQueue(objScheduleHistoryItem);
                    }
                    if (objSchedulerClient.ScheduleHistoryItem.RetainHistoryNum > 0)
                    {
                        EventLogController objEventLog = new EventLogController();
                        LogInfo objEventLogInfo = new LogInfo();
                        objEventLogInfo.AddProperty("THREAD ID", Thread.CurrentThread.GetHashCode().ToString());
                        objEventLogInfo.AddProperty("TYPE", objSchedulerClient.GetType().FullName);
                        if (objException != null)
                        {
                            objEventLogInfo.AddProperty("EXCEPTION", objException.Message);
                        }
                        objEventLogInfo.AddProperty("RESCHEDULED FOR", Convert.ToString(objScheduleHistoryItem.NextStart));
                        objEventLogInfo.AddProperty("SOURCE", objSchedulerClient.ScheduleHistoryItem.ScheduleSource.ToString());
                        objEventLogInfo.AddProperty("ACTIVE THREADS", ActiveThreadCount.ToString());
                        objEventLogInfo.AddProperty("FREE THREADS", FreeThreads.ToString());
                        objEventLogInfo.AddProperty("READER TIMEOUTS", ReaderTimeouts.ToString());
                        objEventLogInfo.AddProperty("WRITER TIMEOUTS", WriterTimeouts.ToString());
                        objEventLogInfo.AddProperty("IN PROGRESS", GetScheduleInProgressCount().ToString());
                        objEventLogInfo.AddProperty("IN QUEUE", GetScheduleQueueCount().ToString());
                        objEventLogInfo.LogTypeKey = "SCHEDULER_EVENT_FAILURE";
                        objEventLog.AddLog(objEventLogInfo);
                    }
                }
                catch (Exception exception1)
                {
    
                    Exception exc = exception1;
                    DotNetNuke.Services.Exceptions.Exceptions.ProcessSchedulerException(exc);
    
                }
            }

            public static void WorkProgressing(ref SchedulerClient objSchedulerClient)
            {
                try
                {
                    if (objSchedulerClient.ScheduleHistoryItem.RetainHistoryNum > 0)
                    {
                        EventLogController objEventLog = new EventLogController();
                        LogInfo objEventLogInfo = new LogInfo();
                        objEventLogInfo.AddProperty("THREAD ID", Thread.CurrentThread.GetHashCode().ToString());
                        objEventLogInfo.AddProperty("TYPE", objSchedulerClient.GetType().FullName);
                        objEventLogInfo.AddProperty("SOURCE", objSchedulerClient.ScheduleHistoryItem.ScheduleSource.ToString());
                        objEventLogInfo.AddProperty("ACTIVE THREADS", ActiveThreadCount.ToString());
                        objEventLogInfo.AddProperty("FREE THREADS", FreeThreads.ToString());
                        objEventLogInfo.AddProperty("READER TIMEOUTS", ReaderTimeouts.ToString());
                        objEventLogInfo.AddProperty("WRITER TIMEOUTS", WriterTimeouts.ToString());
                        objEventLogInfo.AddProperty("IN PROGRESS", GetScheduleInProgressCount().ToString());
                        objEventLogInfo.AddProperty("IN QUEUE", GetScheduleQueueCount().ToString());
                        objEventLogInfo.LogTypeKey = "SCHEDULER_EVENT_PROGRESSING";
                        objEventLog.AddLog(objEventLogInfo);
                    }
                }
                catch (Exception exception1)
                {
    
                    Exception exc = exception1;
                    DotNetNuke.Services.Exceptions.Exceptions.ProcessSchedulerException(exc);
    
                }
            }

            public static void WorkStarted(ref SchedulerClient objSchedulerClient)
            {
                bool ActiveThreadCountIncremented = false;
                try
                {
                    objSchedulerClient.ScheduleHistoryItem.ThreadID = Thread.CurrentThread.GetHashCode();
                    RemoveFromScheduleQueue(objSchedulerClient.ScheduleHistoryItem);
                    AddToScheduleInProgress(objSchedulerClient.ScheduleHistoryItem);
                    Interlocked.Increment(ref ActiveThreadCount);
                    ActiveThreadCountIncremented = true;
                    objSchedulerClient.ScheduleHistoryItem.StartDate = DateAndTime.Now;
                    AddScheduleHistory(objSchedulerClient.ScheduleHistoryItem);
                    if (objSchedulerClient.ScheduleHistoryItem.RetainHistoryNum > 0)
                    {
                        EventLogController objEventLog = new EventLogController();
                        LogInfo objEventLogInfo = new LogInfo();
                        objEventLogInfo.AddProperty("THREAD ID", Thread.CurrentThread.GetHashCode().ToString());
                        objEventLogInfo.AddProperty("TYPE", objSchedulerClient.GetType().FullName);
                        objEventLogInfo.AddProperty("SOURCE", objSchedulerClient.ScheduleHistoryItem.ScheduleSource.ToString());
                        objEventLogInfo.AddProperty("ACTIVE THREADS", ActiveThreadCount.ToString());
                        objEventLogInfo.AddProperty("FREE THREADS", FreeThreads.ToString());
                        objEventLogInfo.AddProperty("READER TIMEOUTS", ReaderTimeouts.ToString());
                        objEventLogInfo.AddProperty("WRITER TIMEOUTS", WriterTimeouts.ToString());
                        objEventLogInfo.AddProperty("IN PROGRESS", GetScheduleInProgressCount().ToString());
                        objEventLogInfo.AddProperty("IN QUEUE", GetScheduleQueueCount().ToString());
                        objEventLogInfo.LogTypeKey = "SCHEDULER_EVENT_STARTED";
                        objEventLog.AddLog(objEventLogInfo);
                    }
                }
                catch (Exception exception1)
                {
    
                    Exception exc = exception1;
                    if (ActiveThreadCountIncremented)
                    {
                        Interlocked.Decrement(ref ActiveThreadCount);
                    }
                    DotNetNuke.Services.Exceptions.Exceptions.ProcessSchedulerException(exc);
    
                }
            }

            public static int FreeThreads
            {
                get
                {
                    return (MaxThreadCount - ActiveThreadCount);
                }
            }

            private static Collection ScheduleInProgress
            {
                get
                {
                    try
                    {
                        objQueueReadWriteLock.AcquireReaderLock(ReadTimeout);
                        try
                        {
                            if (_ScheduleInProgress == null)
                            {
                                _ScheduleInProgress = new Collection();
                            }
                            Interlocked.Increment(ref Reads);
                        }
                        finally
                        {
                            objQueueReadWriteLock.ReleaseReaderLock();
                        }
                    }
                    catch (ApplicationException exception1)
                    {
        
                        ApplicationException ex = exception1;
                        Interlocked.Increment(ref ReadTimeout);
                        DotNetNuke.Services.Exceptions.Exceptions.LogException(ex);
        
                    }
                    return _ScheduleInProgress;
                }
                set
                {
                    try
                    {
                        objQueueReadWriteLock.AcquireWriterLock(WriteTimeout);
                        try
                        {
                            DataCache.SetCache("ScheduleQueue", value);
                            _ScheduleInProgress = value;
                            Interlocked.Increment(ref Writes);
                        }
                        finally
                        {
                            objQueueReadWriteLock.ReleaseWriterLock();
                        }
                    }
                    catch (ApplicationException exception1)
                    {
        
                        ApplicationException ex = exception1;
                        Interlocked.Increment(ref WriterTimeouts);
                        DotNetNuke.Services.Exceptions.Exceptions.LogException(ex);
        
                    }
                }
            }

            private static Collection ScheduleQueue
            {
                get
                {
                    try
                    {
                        objQueueReadWriteLock.AcquireReaderLock(ReadTimeout);
                        try
                        {
                            if (_ScheduleQueue == null)
                            {
                                _ScheduleQueue = new Collection();
                            }
                            Interlocked.Increment(ref Reads);
                        }
                        finally
                        {
                            objQueueReadWriteLock.ReleaseReaderLock();
                        }
                    }
                    catch (ApplicationException exception1)
                    {
        
                        ApplicationException ex = exception1;
                        Interlocked.Increment(ref ReadTimeout);
                        DotNetNuke.Services.Exceptions.Exceptions.LogException(ex);
        
                    }
                    return _ScheduleQueue;
                }
                set
                {
                    try
                    {
                        objQueueReadWriteLock.AcquireWriterLock(WriteTimeout);
                        try
                        {
                            DataCache.SetCache("ScheduleQueue", value);
                            _ScheduleQueue = value;
                            Interlocked.Increment(ref Writes);
                        }
                        finally
                        {
                            objQueueReadWriteLock.ReleaseWriterLock();
                        }
                    }
                    catch (ApplicationException exception1)
                    {
        
                        ApplicationException ex = exception1;
                        Interlocked.Increment(ref WriterTimeouts);
                        DotNetNuke.Services.Exceptions.Exceptions.LogException(ex);
        
                    }
                }
            }
        }
    }
}

